package co.yixiang.yshop.module.cart.service.storecart;

import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import co.yixiang.yshop.framework.common.constant.CartConstant;
import co.yixiang.yshop.framework.common.constant.ShopConstants;
import co.yixiang.yshop.framework.common.enums.OrderInfoEnum;
import co.yixiang.yshop.framework.common.enums.ShopCommonEnum;
import co.yixiang.yshop.framework.common.exception.ErrorCode;
import co.yixiang.yshop.module.cart.controller.app.cart.param.AppCartChangeSkuParam;
import co.yixiang.yshop.module.cart.convert.storecart.StoreCartConvert;
import co.yixiang.yshop.module.cart.dal.dataobject.storecart.StoreCartDO;
import co.yixiang.yshop.module.cart.dal.mysql.storecart.StoreCartMapper;
import co.yixiang.yshop.module.cart.enums.CartTypeEnum;
import co.yixiang.yshop.module.cart.enums.OrderTypeEnum;
import co.yixiang.yshop.module.product.controller.app.campaigninfo.vo.CampaignSkuVO;
import co.yixiang.yshop.module.product.controller.app.cart.vo.AppStoreCartQueryVo;
import co.yixiang.yshop.module.product.controller.app.couponrelation.vo.CartCouponVO;
import co.yixiang.yshop.module.product.controller.app.product.vo.AppStoreProductRespVo;
import co.yixiang.yshop.module.product.dal.dataobject.storeproduct.StoreProductDO;
import co.yixiang.yshop.module.product.dal.dataobject.storeproductattrvalue.StoreProductAttrValueDO;
import co.yixiang.yshop.module.product.service.campaigninfo.AppCampaignInfoService;
import co.yixiang.yshop.module.product.service.productcouponrelation.AppCouponRelationService;
import co.yixiang.yshop.module.product.service.productcouponrelation.dto.CartCouponDTO;
import co.yixiang.yshop.module.product.service.storeproduct.AppStoreProductService;
import co.yixiang.yshop.module.product.service.storeproductattrvalue.StoreProductAttrValueService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

import static co.yixiang.yshop.framework.common.exception.util.ServiceExceptionUtil.exception;
import static co.yixiang.yshop.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
import static co.yixiang.yshop.module.cart.enums.ErrorCodeConstants.*;
import static co.yixiang.yshop.module.product.enums.ErrorCodeConstants.STORE_PRODUCT_NOT_EXISTS;

/**
 * 购物车 Service 实现类
 *
 * @author yshop
 */
@Slf4j
@Service
@Validated
public class AppStoreCartServiceImpl extends ServiceImpl<StoreCartMapper, StoreCartDO> implements AppStoreCartService {

    @Resource
    private StoreCartMapper storeCartMapper;
    @Resource
    private AppStoreProductService appStoreProductService;
    @Resource
    private StoreProductAttrValueService storeProductAttrValueService;

    @Resource
    private AppCouponRelationService couponRelationService;

    @Resource
    private AppCampaignInfoService appCampaignInfoService;


    /**
     * 返回当前用户购物车总数量
     *
     * @param uid 用户id
     * @return int
     */
    @Override
    public int getUserCartNum(Long uid) {
        return storeCartMapper.cartSum(uid);
    }

    /**
     * 添加购物车
     *
     * @param uid               用户id
     * @param productId         普通产品编号
     * @param cartNum           购物车数量
     * @param productAttrUnique 属性唯一值
     * @param isNew             1 加入购物车直接购买  0 加入购物车
     * @param combinationId     拼团id
     * @param seckillId         秒杀id
     * @param bargainId         砍价id
     * @return 购物车id
     */
    @Override
    public long addCart(Long uid, Long productId, Integer cartNum, String productAttrUnique,
                        Integer isNew, Long combinationId, Long seckillId, Long bargainId, Long integralShopId, Integer orderType) {

        LambdaQueryWrapper<StoreCartDO> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(StoreCartDO::getUid, uid)
                .eq(StoreCartDO::getIsPay, OrderInfoEnum.PAY_STATUS_UNPAID.getValue())
                .eq(StoreCartDO::getProductId, productId)
                .eq(StoreCartDO::getIsNew, isNew)
                .eq(StoreCartDO::getProductAttrUnique, productAttrUnique)
                .eq(StoreCartDO::getBargainId, bargainId)
                .eq(StoreCartDO::getCombinationId, combinationId)
                .eq(StoreCartDO::getSeckillId, seckillId)
                .eq(StoreCartDO::getIntegralShopId, integralShopId)
                .orderByDesc(StoreCartDO::getId)
                .last("limit 1");

        StoreCartDO cart = storeCartMapper.selectOne(wrapper);

        //加入购物车才累计，立即购买不用累计
        if (cart != null && CartTypeEnum.ADD_SHOPPING_CART.getValue().equals(isNew)) {
            cartNum = cartNum + cart.getCartNum();
        }
        this.checkProductStock(uid, productId, cartNum, productAttrUnique, orderType);

        StoreCartDO storeCart = StoreCartDO.builder()
                .cartNum(cartNum)
                .productAttrUnique(productAttrUnique)
                .productId(productId)
                .bargainId(bargainId)
                .combinationId(combinationId)
                .seckillId(seckillId)
                .integralShopId(integralShopId)
                .isNew(isNew)
                .uid(uid)
                .build();
        if (cart != null) {
            storeCart.setId(cart.getId());
            storeCartMapper.updateById(storeCart);
        } else {
            storeCartMapper.insert(storeCart);
        }

        return storeCart.getId();
    }

    /**
     * 检测商品库存 库存加锁
     *
     * @param uid               用户ID
     * @param productId         产品ID
     * @param cartNum           购买数量
     * @param productAttrUnique 商品属性Unique
     */
    @Override
    public void checkProductStock(Long uid, Long productId, Integer cartNum, String productAttrUnique, Integer type) {
        StoreProductDO product = appStoreProductService
                .lambdaQuery().eq(StoreProductDO::getId, productId)
                .eq(StoreProductDO::getIsShow, ShopCommonEnum.SHOW.getValue())
                .one();
        if (product == null) {
            throw exception(STORE_PRODUCT_NOT_EXISTS);
        }
        int stock = appStoreProductService.getProductStock(productId, productAttrUnique, type, cartNum);
        if (stock < cartNum) {
            throw exception(new ErrorCode(1008003010, product.getStoreName() + "库存不足" + cartNum));
        }

    }


    /**
     * 购物车列表
     *
     * @param uid     用户id
     * @param cartIds 购物车id，多个逗号隔开
     * @param status  0-购购物车列表，2-活动商品
     * @return map valid-有效购物车 invalid-失效购物车
     */
    @Override
    public Map<String, Object> getUserProductCartList(Long uid, String cartIds, Integer status) {
        LambdaQueryWrapper<StoreCartDO> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(StoreCartDO::getUid, uid)
                .eq(StoreCartDO::getIsPay, OrderInfoEnum.PAY_STATUS_UNPAID.getValue())
                .eq(status == null, StoreCartDO::getIsNew, CartTypeEnum.ADD_SHOPPING_CART.getValue())
                .in(StrUtil.isNotEmpty(cartIds), StoreCartDO::getId, Arrays.asList(cartIds.split(",")))
                .orderByDesc(StoreCartDO::getId)
        ;
        List<StoreCartDO> carts = storeCartMapper.selectList(wrapper);

        List<AppStoreCartQueryVo> valid = new ArrayList<>();
        List<AppStoreCartQueryVo> invalid = new ArrayList<>();

        Map<Long, AppStoreProductRespVo> productMap = null;
        Map<String, StoreProductAttrValueDO> skuMap = null;
        //活动商品详情
        Map<String, CampaignSkuVO> campaignSkuVOMap = null;
        //查询出下单的商品规格相关的信息
        if (CollectionUtils.isNotEmpty(carts)) {
            // 查询商品列表
            List<Long> productIds = carts.stream()
                    .map(StoreCartDO::getProductId).collect(Collectors.toList());
            List<AppStoreProductRespVo> products = appStoreProductService.getStoreProductByIds(productIds);
            productMap = products.stream()
                    .collect(Collectors.toMap(AppStoreProductRespVo::getId, Function.identity()));
            // 查询商品规格列表
            List<String> skuUniques = carts.stream()
                    .map(StoreCartDO::getProductAttrUnique).collect(Collectors.toList());
            List<StoreProductAttrValueDO> skus = storeProductAttrValueService.list(
                    Wrappers.<StoreProductAttrValueDO>lambdaQuery().in(StoreProductAttrValueDO::getUnique, skuUniques)
            );
            skuMap = skus.stream()
                    .collect(Collectors.toMap(StoreProductAttrValueDO::getUnique, Function.identity()));
            // 活动下单查询
            if (OrderInfoEnum.CAMPAIGN_ORDER.getValue().equals(status)) {
                //通过商品规格唯一序列查询出活动的商品规格信息
                List<CampaignSkuVO> campaignSkuVOS = appCampaignInfoService.getCampaignsByProductAttrUniques(skuUniques);
                if (CollectionUtils.isEmpty(campaignSkuVOS)) {
                    throw exception(CAMPAIGN_NOT_EXISTS);
                }
                campaignSkuVOMap = campaignSkuVOS.stream()
                        .collect(Collectors.toMap(CampaignSkuVO::getProductAttrUnique, Function.identity()));
            }
        }

        for (StoreCartDO storeCart : carts) {
            String unique = storeCart.getProductAttrUnique();
            AppStoreProductRespVo storeProduct = productMap.get(storeCart.getProductId());
            //转换重构的obj
            AppStoreCartQueryVo storeCartQueryVo = StoreCartConvert.INSTANCE.convert01(storeCart);
            if (ObjectUtil.isNull(storeProduct)) {
                this.removeById(storeCart.getId());
            } else if (ShopCommonEnum.NO_SHOW.getValue().equals(storeProduct.getIsShow())
                    || (storeProduct.getStock() == 0 && StrUtil.isEmpty(unique))
            ) {
                storeCartQueryVo.setProductInfo(storeProduct);
                invalid.add(storeCartQueryVo);
            } else {
                StoreProductAttrValueDO productAttrValue = skuMap.get(unique);
                //库存
                Integer attrStork = productAttrValue.getStock();
                CampaignSkuVO campaignSkuVO = null;
                //  判断是不是是不是活动下单，是活动的话，使用活动库存作为计算库存
                if (ObjectUtil.isNotNull(campaignSkuVOMap) && campaignSkuVOMap.containsKey(unique)) {
                    campaignSkuVO = campaignSkuVOMap.get(unique);
                    attrStork = campaignSkuVO.getStock();
                }
                if (ObjectUtil.isNull(productAttrValue) || attrStork == 0) {
                    storeCartQueryVo.setProductInfo(storeProduct);
                    invalid.add(storeCartQueryVo);
                } else {
                    storeProduct.setAttrInfo(productAttrValue);
                    storeCartQueryVo.setProductInfo(storeProduct);
                    // 普通商品金额
                    BigDecimal truePrice = productAttrValue.getPrice();
                    Integer stock = attrStork;
                    // 设置拼团价格
                    if (storeCart.getCombinationId() > 0) {
                        truePrice = productAttrValue.getPinkPrice();
                    }
                    // 设置秒杀价格
                    if (storeCart.getSeckillId() > 0) {
                        truePrice = productAttrValue.getSeckillPrice();
                    }
                    // 设置活动价格
                    if (campaignSkuVO != null) {
                        truePrice = campaignSkuVO.getPrice();
                        storeCartQueryVo.setUseIntegral(campaignSkuVO.getIntegral());
                    }
                    storeCartQueryVo.setTruePrice(truePrice);
                    storeCartQueryVo.setTrueStock(stock);
                    valid.add(storeCartQueryVo);
                }
            }

        }

        Map<String, Object> map = new LinkedHashMap<>();
        map.put(CartConstant.VAILD_KEY, valid);
        map.put(CartConstant.INVAILD_KEY, invalid);
        return map;
    }

    /**
     * 改购物车数量
     *
     * @param cartId  购物车id
     * @param cartNum 数量
     * @param uid     uid
     */
    @Override
    public void changeUserCartNum(Long cartId, int cartNum, Long uid) {
        StoreCartDO cart = this.lambdaQuery()
                .eq(StoreCartDO::getUid, uid)
                .eq(StoreCartDO::getId, cartId)
                .one();
        if (cart == null) {
            throw exception(STORE_CART_NOT_EXISTS);
        }

        if (cartNum <= 0) {
            throw exception(STORE_STOCK_ERROR);
        }

        //普通商品库存
        int stock = appStoreProductService.getProductStock(cart.getProductId(), cart.getProductAttrUnique(), OrderTypeEnum.NORMAL_ORDER.getValue(), cartNum);
        if (stock < cartNum) {
            throw exception(new ErrorCode(1008006002, "该产品库存不足" + cartNum));
        }

        if (cartNum == cart.getCartNum()) {
            return;
        }

        StoreCartDO storeCart = new StoreCartDO();
        storeCart.setCartNum(cartNum);
        storeCart.setId(cartId);

        storeCartMapper.updateById(storeCart);


    }


    /**
     * 删除购物车
     *
     * @param uid uid
     * @param ids 购物车id集合
     */
    @Override
    public void removeUserCart(Long uid, List<String> ids) {
        List<Long> newIds = ids.stream().map(Long::new).collect(Collectors.toList());
        storeCartMapper.delete(Wrappers.<StoreCartDO>lambdaQuery()
                .eq(StoreCartDO::getUid, uid)
                .in(StoreCartDO::getId, newIds));
    }

    /**
     * 修改购物车支付状态
     *
     * @param cartIds 购物车id列表
     */
    @Async
    @Override
    //@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void updateCartPayStatus(List<String> cartIds) {
        log.info("==========修改购物车支付状态start===========");
        StoreCartDO cartObj = new StoreCartDO();
        cartObj.setIsPay(OrderInfoEnum.PAY_STATUS_HAVE_PAID.getValue());
        storeCartMapper.update(cartObj, Wrappers.<StoreCartDO>lambdaQuery()
                .in(StoreCartDO::getId, cartIds));
    }

    @Override
    public void changeSku(Long uid, AppCartChangeSkuParam param) {
        StoreCartDO cart = this.lambdaQuery()
                .eq(StoreCartDO::getUid, uid)
                .eq(StoreCartDO::getId, param.getId())
                .one();
        if (cart == null) {
            throw exception(STORE_CART_NOT_EXISTS);
        }
        cart.setProductAttrUnique(param.getProductAttrUnique());
        storeCartMapper.update(cart, Wrappers.<StoreCartDO>lambdaQuery()
                .eq(StoreCartDO::getId, param.getId()));
    }

    @Override
    public List<CartCouponVO> searchCartAvailableCoupon(String cartIds) {
        Long uid = getLoginUserId();
        Map<String, Object> cartGroup = getUserProductCartList(uid, cartIds, ShopConstants.YSHOP_ONE_NUM);
        List<AppStoreCartQueryVo> cartInfo = (List<AppStoreCartQueryVo>) cartGroup.get(CartConstant.VAILD_KEY);
        List<CartCouponDTO> cartCouponDtoList = new ArrayList<>();
        for (AppStoreCartQueryVo vo : cartInfo) {
            cartCouponDtoList.add(new CartCouponDTO(vo.getProductId(), vo.getProductAttrUnique(), NumberUtil.mul(vo.getTruePrice(), vo.getCartNum())));
        }
        return couponRelationService.searchCartCoupon(cartCouponDtoList, null);
    }
}
